package TrafficControlSystem.TrafficServer;

import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.geom.Ellipse2D;
import java.util.Observable;
import java.util.Observer;

import javax.swing.JOptionPane;
import javax.swing.JPanel;

import TrafficControlSystem.Common.Car;
import TrafficControlSystem.Common.CarsInfo;
import TrafficControlSystem.Common.LightsInfo;
import TrafficControlSystem.Common.LightsInfo.LightsState;

@SuppressWarnings("serial")
public class SimulationView extends JPanel implements Observer {
	
	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		float w = getWidth();
		float h = getHeight();
		float d = Math.min(w, h);
				
		scale = Math.min(h, w)/460.0f;
		offsetX = (w - d)/2;
		offsetY = (h - d)/2;
		
		Graphics2D g2d = (Graphics2D) g;
		
		g2d.setColor(new Color(173, 208, 138));
		for (int y = 0; y < 4; ++y) {
			for (int x = 0; x < 4; ++x) {
				g2d.fill(new Rectangle.Float(x*120*scale + offsetX, y*120*scale + offsetY, 100*scale, 100*scale));
			}
		}

		g2d.setColor(Color.gray);
		float y = 100;
		for (int i = 0; i < 3; ++i) {
			g2d.fill(new Rectangle.Float(offsetX, y*scale + offsetY, 460*scale, 20*scale));
			g2d.fill(new Rectangle.Float(y*scale + offsetX, offsetY, 20*scale, 460*scale));
			y += 120;
		}

		LightsInfo lights = TrafficServer.getInstance().getLights();
		if (lights != null) {
			
			Color redSolid = new Color(1.0f, 0.0f, 0.0f, 0.8f);
			Color redTransparent = new Color(0.50f, 0.0f, 0.0f, 0.0f);
			Color greenSolid = new Color(0.0f, 1.0f, 0.0f, 0.8f);
			Color greenTransparent = new Color(0.0f, 0.5f, 0.0f, 0.0f);
			
			for (ly = 0; ly < 3; ++ly) {
				for (lx = 0; lx < 3; ++lx) {
					LightsState light = lights.getStates()[3*ly+lx];
					
					if (light == LightsState.HORIZONTALLY_GREEN) {
						// zielone
						g2d.setPaint(new GradientPaint(X(60), Y(100), greenTransparent, X(100), Y(100), greenSolid));
						g2d.fill(new Rectangle.Float(X(60), Y(100), 40 * scale, 20*scale));
						
						g2d.setPaint(new GradientPaint(X(120), Y(100), greenSolid , X(160), Y(100), greenTransparent));
						g2d.fill(new Rectangle.Float(X(120), Y(100), 40 * scale, 20*scale));	
						
						// czerwone
						g2d.setPaint(new GradientPaint(X(100), Y(90), redTransparent, X(100), Y(100), redSolid));
						g2d.fill(new Rectangle.Float(X(100), Y(90), 20 * scale, 10 * scale));
						
						g2d.setPaint(new GradientPaint(X(100), Y(120), redSolid, X(100), Y(130), redTransparent));
						g2d.fill(new Rectangle.Float(X(100), Y(120), 20 * scale, 10 * scale));
					} else {
						// czerwone
						g2d.setPaint(new GradientPaint(X(90), Y(100), redTransparent, X(100), Y(100), redSolid));
						g2d.fill(new Rectangle.Float(X(90), Y(100), 10 * scale, 20*scale));
						
						g2d.setPaint(new GradientPaint(X(120), Y(100), redSolid , X(130), Y(100), redTransparent));
						g2d.fill(new Rectangle.Float(X(120), Y(100), 10 * scale, 20*scale));
						
						// zielone
						g2d.setPaint(new GradientPaint(X(100), Y(60), greenTransparent, X(100), Y(100), greenSolid));
						g2d.fill(new Rectangle.Float(X(100), Y(60), 20 * scale, 40 * scale));
						
						g2d.setPaint(new GradientPaint(X(100), Y(120), greenSolid, X(100), Y(160), greenTransparent));
						g2d.fill(new Rectangle.Float(X(100), Y(120), 20 * scale, 40 * scale));
						
					}
					
					g2d.setColor(greenSolid);
					g2d.fill(new Rectangle.Float(X(100), Y(100), 20 * scale, 20 * scale));
					
					
				}
			}
			
		}
		
		CarsInfo carsInfo = TrafficServer.getInstance().getCars();
		if (carsInfo != null) {
			for (Car car : carsInfo.getCars()) {
				float cx,cy,cw,ch;
				cx = (car.getX()*10)*scale + offsetX;
				cy = (car.getY()*10)*scale + offsetY;
				cw = 10*scale;
				ch = 10*scale;
				g2d.setColor(car.getColor());
				g2d.fill(new Ellipse2D.Float(cx, cy, cw, ch));
			}
		}
	}
	
	@Override
	public void update(Observable o, Object arg) {
		System.out.println("Update");
		repaint();
	}
	
	private float X(float x) {
		return (x + lx * 120) * scale + offsetX;
	}
	
	private float Y(float y) {
		return (y + ly * 120) * scale + offsetY;
	}
	
	private float scale;
	private float offsetX;
	private float offsetY;
	private int lx, ly;
}
